# Copyright (c) 2020 The Orbit Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

cmake_minimum_required(VERSION 3.15)

project(Orbit C CXX)

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  set(STRICT_COMPILE_FLAGS -Werror=all
                           -Werror=float-conversion
                           -Werror=format=2
                           -Werror=inconsistent-missing-override
                           -Werror=old-style-cast
                           -Werror=unused-parameter
                           -Werror=unused-variable
                           -Werror=sign-compare)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  set(STRICT_COMPILE_FLAGS -Werror=all
                           -Werror=float-conversion
                           -Werror=format=2
                           -Werror=old-style-cast
                           -Werror=unused-parameter
                           -Werror=unused-variable
                           -Werror=sign-compare)
endif()

include(cmake/strip.cmake)
include(cmake/tests.cmake)
enable_testing()

option(WITH_GUI "Setting this option will enable the Qt-based UI client." ON)
option(WITH_FUZZING "Setting this option will enable the fuzzing mode." OFF)
option(WITH_CRASH_HANDLING "Setting this option will enable crash handling based on crashpad." ON)

set(CRASHDUMP_SERVER "" CACHE STRING "Setting this option will enable uploading crash dumps to the url specified.")

set(CMAKE_CXX_STANDARD 17)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
conan_basic_setup(TARGETS)

if (NOT WIN32)
  # Make all executables position independent on Linux

  # Note that we need to have both. If we omit "-pie"
  # option executables are built as ET_EXEC, if we
  # omit set(CMAKE_POSITION_INDEPENDENT_CODE ON)
  # Ninja configuration stops working because for
  # some reason in config stage it compile code for tests
  # without -fPIC but tries to link them with -pie

  string(APPEND CMAKE_EXE_LINKER_FLAGS " -pie")
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()

# This line is necessary to pick up the cmake-config-files
# generated by conan first.
list(PREPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")

# This line is necessary to pick up the cmake-config-files
# generated by conan under cross compilation conditions.
list(PREPEND CMAKE_FIND_ROOT_PATH "${CMAKE_BINARY_DIR}")

# This line is necessary to pick up package-provided cmake-
# scripts in a cross compilation environment.
list(APPEND CMAKE_FIND_ROOT_PATH "${CONAN_CMAKE_MODULE_PATH}")

# Temporary workaround for GRPC as long as
# conan does not support library components yet.
# This ensures that cmake will use the library-provided
# cmake config files instead of the conan-generated ones.
list(PREPEND CMAKE_PREFIX_PATH "${CONAN_GRPC_ROOT}")
list(PREPEND CMAKE_FIND_ROOT_PATH "${CONAN_GRPC_ROOT}")

if(NOT WIN32 AND (WITH_GUI OR WITH_FUZZING))
  find_package(X11 REQUIRED)
endif()

find_package(OpenSSL CONFIG REQUIRED)
find_package(Threads REQUIRED)
find_package(cereal CONFIG REQUIRED)
find_package(xxHash REQUIRED)
find_package(multicore REQUIRED)
find_package(concurrentqueue REQUIRED)
find_package(gte REQUIRED)
find_package(protobuf CONFIG REQUIRED)

# Conan's protobuf target is called protobuf::protobuf while
# the original one is called protobuf::libprotobuf, so we create
# an alias here to make it work with packages requiring the original
# name like gRPC.
add_library(protobuf::libprotobuf INTERFACE IMPORTED)
target_link_libraries(protobuf::libprotobuf INTERFACE protobuf::protobuf)
include("third_party/protobuf/protobuf-generate.cmake")

find_package(gRPC CONFIG REQUIRED)


if(WITH_GUI OR WITH_FUZZING)
  find_package(freetype CONFIG REQUIRED)
  find_package(freetype-gl CONFIG REQUIRED)
  find_package(OpenGL REQUIRED)
  find_package(glew CONFIG REQUIRED)
  find_package(imgui CONFIG REQUIRED)
  find_package(libssh2 CONFIG REQUIRED)
endif()

find_package(oqpi REQUIRED)
find_package(stb REQUIRED)
find_package(capstone CONFIG REQUIRED)

if(WITH_GUI)
  find_package(Qt5 CONFIG REQUIRED COMPONENTS Core Network Widgets)
  find_package(qtpropertybrowser REQUIRED)
endif()

if(WITH_GUI AND WITH_CRASH_HANDLING)
  find_package(crashpad CONFIG REQUIRED)
endif()

find_package(abseil CONFIG REQUIRED)
find_package(llvm_object CONFIG REQUIRED)
find_package(Outcome CONFIG REQUIRED)

if(NOT WIN32)
  find_package(libunwindstack CONFIG REQUIRED)
endif()

find_package(asio CONFIG REQUIRED)
find_package(GTest REQUIRED)
find_package(GMock REQUIRED)
find_package(Filesystem REQUIRED)

if (WITH_FUZZING)
  find_package(libprotobuf-mutator CONFIG REQUIRED)
endif()

# Set preprocessor defines These are only necessary for windows, but we will
# define them on all platforms, to keep the builds similar as possible.
add_definitions(-DNOMINMAX)
add_definitions(-DUNICODE -D_UNICODE)

if(WITH_FUZZING)
  add_definitions(-DORBIT_FUZZING=1)
endif()

if(WIN32)
  add_definitions(-DWIN32)
else()
  add_subdirectory(OrbitLinuxTracing)
  add_subdirectory(OrbitService)
endif()

add_subdirectory(ElfUtils)
add_subdirectory(OrbitBase)
add_subdirectory(OrbitCore)
add_subdirectory(OrbitFramePointerValidator)
add_subdirectory(OrbitTest)
add_subdirectory(protos)

if(WITH_GUI)
  add_subdirectory(OrbitGgp)
  add_subdirectory(OrbitSsh)
  add_subdirectory(OrbitSshQt)
endif()

if(WITH_GUI OR WITH_FUZZING)
  add_subdirectory(OrbitGl)
endif()

if (WITH_GUI)
  add_subdirectory(OrbitQt)
endif()

if (WITH_FUZZING)
  add_subdirectory(OrbitFuzzing)
endif()

if(WIN32)
  # Startup Project
  set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT
                                                              "OrbitQt")
endif()

# Collecting third-party licenses
file(COPY third_party/concurrentqueue/LICENSE.md DESTINATION ${CMAKE_BINARY_DIR}/licenses/concurrentqueue/)
file(COPY third_party/multicore/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/multicore/)
file(COPY third_party/xxHash-r42/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/xxhash/)
file(COPY third_party/gte/LICENSE_1_0.txt DESTINATION ${CMAKE_BINARY_DIR}/licenses/gte/)
file(COPY third_party/oqpi/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/oqpi/)
file(COPY third_party/Qt/LICENSE.LGPLv3 DESTINATION ${CMAKE_BINARY_DIR}/licenses/Qt/)
file(COPY third_party/Outcome/LICENCE DESTINATION ${CMAKE_BINARY_DIR}/licenses/Outcome/licenses/)
file(COPY third_party/capstone/LICENSE.TXT DESTINATION ${CMAKE_BINARY_DIR}/licenses/capstone/licenses/)
file(COPY third_party/LLVM/LICENSE.TXT DESTINATION ${CMAKE_BINARY_DIR}/licenses/LLVM/licenses/)
file(COPY third_party/libunwindstack/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/libunwindstack/licenses/)
file(COPY third_party/lzma_sdk/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/lzma_sdk/licenses/)
file(COPY third_party/freetype-gl/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/freetype-gl/licenses/)
file(COPY third_party/fonts/VERA-COPYRIGHT DESTINATION ${CMAKE_BINARY_DIR}/licenses/fonts/)
file(COPY third_party/OpenSSL/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/openssl/licenses/)
file(COPY third_party/qtpropertybrowser/LICENSE.txt DESTINATION ${CMAKE_BINARY_DIR}/licenses/qtpropertybrowser/licenses/)
file(COPY third_party/conan/LICENSE.md DESTINATION ${CMAKE_BINARY_DIR}/licenses/conan/licenses/)
file(COPY third_party/stb/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/licenses/stb/licenses/)
file(REMOVE ${CMAKE_BINARY_DIR}/licenses/freetype/licenses/LICENSE.TXT)
file(REMOVE ${CMAKE_BINARY_DIR}/licenses/freetype/licenses/GPLv2.TXT)
include("cmake/collect_licenses.cmake")
GenerateThirdPartyLicenseFile("${CMAKE_BINARY_DIR}/NOTICE" "${CMAKE_BINARY_DIR}/licenses/")
